package cc.mrbird.febs.common.utils;

import java.util.Base64;
import java.util.Date;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.exception.TokenInvalidException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
 * JWT Token封装工具类
 *
 * @author Lord
 */
public class TokenUtil {

    /**
     * 解析JWT token字符串
     * @param token
     * @return
     * @throws Exception
     */
    public static Claims getClaimsByToken(String token) {
        try {
            return Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            throw new TokenInvalidException("Token认证出错");
        }
    }

    /**
     * 刷新token有效期
     * @param claims
     * @return 重新生成的token
     */
    public static String refreshToken(Claims claims) {
        if (ObjectUtil.isNull(claims)) {
            throw new TokenInvalidException("Token认证出错");
        }

        try {
            String refreshedToken = generateToken(claims, FebsConstant.JWT_H5_TTL);
            if (StrUtil.isEmpty(refreshedToken)) {
                throw new TokenInvalidException("Token认证出错");
            }

            return refreshedToken;
        } catch (Exception e) {
            throw new TokenInvalidException("Token认证出错");
        }
    }

    /**
     * 生成token
     * @param platform 平台类型，枚举
     * @param claims 自定义属性
     * @param jwtTtl token有效时间
     * @return
     */
    public static String generateToken(Map<String, Object> claims, int jwtTtl) {
        try {
            claims.put("domain", FebsConstant.DOMAIN);

            long nowMillis = System.currentTimeMillis();
            Date now = new Date(nowMillis);
            JwtBuilder builder = Jwts.builder().setIssuer("febs").setIssuedAt(now).setId(FebsConstant.JWT_ID)
                    .setSubject(claims.get("memberId").toString()).setClaims(claims)
                    .signWith(SignatureAlgorithm.HS256, generalKey());
            if (jwtTtl > 0) {
                long expMillis = nowMillis + jwtTtl;
                Date expDate = new Date(expMillis);
                builder.setExpiration(expDate);
            }
            return builder.compact();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 由字符串生成加密key
     * @return
     */
    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(FebsConstant.JWT_SECRET);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

}
